﻿using System;

namespace Cpu6502
{

    public class Registers
    {        
        /// <summary>
        /// Accumulator
        /// </summary>
        public Byte A = 0;

        /// <summary>
        /// General purpose X Register
        ///</summary>
        public Byte X = (byte)0;

        /// <summary>
        /// General purpose Y Register
        /// </summary>
        public Byte Y = (byte)0;

        /// <summary>
        /// Stack Pointer
        /// </summary>
        public Byte S = 0;

        /// <summary>
        /// Processor Status
        /// </summary>
        public PRegister P = new PRegister();

        /// <summary>
        /// Holds Processor Flags, Broken out so its easier to work with than mashing bits all the time.
        ///    7                           0
        ///  +---+---+---+---+---+---+---+---+
        ///  | N | V |   | B | D | I | Z | C |  
        ///  +---+---+---+---+---+---+---+---+
        /// </summary>
        public class PRegister
        {


            private Byte _value = (byte)0;

            /// <summary>
            /// NEGATIVE. Set if bit 7 of the accumulator is set.
            /// </summary>
            public bool N = false;

            /// <summary>
            /// OVERFLOW. Set if the addition of two like-signed numbers or the
            /// subtraction of two unlike-signed numbers produces a result
            /// greater than +127 or less than -128.
            /// </summary>
            public bool V = false;

            /// <summary>
            /// BRK COMMAND. Set if an interrupt caused by a BRK, reset if
            /// caused by an external interrupt.
            /// </summary>
            public bool B = false;

            /// <summary>
            /// DECIMAL MODE. Set if decimal mode active.
            /// </summary>
            public bool D = false;

            /// <summary>
            /// IRQ DISABLE.  Set if maskable interrupts are disabled.
            /// </summary>
            public bool I = false;

            /// <summary>
            /// ZERO.  Set if the result of the last operation (load/inc/dec/
            /// add/sub) was zero.
            /// </summary>
            public bool Z = false;

            /// <summary>
            /// CARRY. Set if the add produced a carry, or if the subtraction
            /// produced a borrow.  Also holds bits after a logical shift.
            /// </summary>     
            public bool C = false;

            public Byte Value
            {
                get
                {
                    _value = unchecked
                    (
                        (byte)
                        (
                            (this.C ? 1 : 0) |
                            (this.Z ? 2 : 0) |
                            (this.I ? 4 : 0) |
                            (this.D ? 8 : 0) |
                            (this.B ? 16 : 0) |
                            1 |
                            (this.V ? 64 : 0) |
                            (this.N ? 128 : 0)
                        )
                    );

                    return _value;
                }

                set
                {
                    _value = value;
                    this.C = (((_value << 0) & 1) == 1);
                    this.Z = (((_value << 1) & 1) == 1);
                    this.I = (((_value << 2) & 1) == 1);
                    this.D = (((_value << 3) & 1) == 1);
                    this.B = (((_value << 4) & 1) == 1);
                    this.V = (((_value << 6) & 1) == 1);
                    this.N = (((_value << 7) & 1) == 1);
                }
            }
        }

    }




}
